home *** CD-ROM | disk | FTP | other *** search
/ The PC-SIG Library 9 / The PC-SIG Library on CD ROM - Ninth Edition.iso / 001_100 / DISK0041 / DISK0041.ZIP / MSSEND.ASM < prev    next >
Assembly Source File  |  1984-12-08  |  33KB  |  1,064 lines

  1.     public    spar, rpar, error, error1, nout, send, flags, trans, pack
  2.     public    dodec, doenc, curchk, inichk, packlen, send11
  3.     include msdefs.h    
  4.  
  5. spmin    equ    20        ; Minimum packet size.
  6. spmax    equ    94        ; Maximum packet size.
  7.  
  8. datas     segment    public 'datas'
  9.     extrn    buff:byte, data:byte, fcb:byte, cpfcb:byte, filbuf:byte
  10.     extrn    decbuf:byte, chrcnt:word, bufpnt:word, comand:byte
  11.     extrn    rptq:byte, origr:byte, rptct:byte, rptval:byte
  12.  
  13. flags    flginfo    <>
  14. trans    trinfo    <>
  15. pack    pktinfo <>
  16. crlf    db    cr,lf,'$'
  17. ender    db    bell,bell,'$'             ;  [4]
  18. erms14  db    '?Unable to receive an acknowledgment from the host$'
  19. erms15  db    '?Unable to find file$'
  20. erms20    db    'Unable to send init packet$'
  21. erms21    db    'Unable to send file header$'
  22. erms22    db    'Unable to send data$'
  23. erms23    db    'Unable to send end-of-file packet$'
  24. erms24    db    'Unable to send break packet$'
  25. infms2  db    cr,'             Sending: In progress$'
  26. infms3  db    'Completed$'
  27. infms4  db    'Failed$'
  28. infms6  db    'Interrupted$'
  29. infms7    db    cr,' Percent transferred: 100%$'
  30. remmsg1    db    'Kermit-MS: File not found$'
  31. filhlp  db      ' Input file spec (possibly wild) $'
  32. filmsg    db    ' File name to use on target system or confirm with'
  33.     db    ' a carriage return $'
  34.  
  35. curchk    db    0        ; Use to store checksum length.
  36. inichk    db    1        ; Original or set checksum length.
  37. chrptr  dw    ?        ; Position in character buffer.
  38. fcbpt    dw    ?        ; Position in FCB.
  39. datptr  dw    ?        ; Position in packet data buffer.
  40. siz    dw    ?        ; Size of data from gtchr.
  41. temp    dw    0
  42. temp4    dw    0
  43. sendas    dw    50 dup(0)    ; Buffer for file name.
  44. difnam    db    0        ; Send under different name?
  45. difsiz    db    0        ; Size of new file name.
  46. asmsg    db    '  as  $'
  47. filopn    db    0        ; Says if disk file is open.
  48. datas    ends
  49.  
  50. code    segment    public
  51.     extrn serini:near, serrst:near, comnd:near, init:near
  52.     extrn spack:near, rpack:near, gtnfil:near, gtchr:near
  53.     extrn getfil:near, clrfln:near, nppos:near, rprpos:near
  54.     extrn erpos:near, rtpos:near, cxmsg:near, stpos:near
  55.     extrn encode:near, nulref:near, decode:near, nulr:near
  56.     extrn errpack:near, updrtr:near, clrmod:near, fcbcpy:near
  57.     extrn perpos:near
  58.     assume    cs:code,ds:datas
  59.  
  60. ;    This routine sets up the data for init packet (either the
  61. ;    Send_init or ACK packet).
  62.  
  63. RPAR    PROC    NEAR
  64.     mov ah,trans.rpsiz    ; Get the receive packet size.
  65.     add ah,' '        ; Add a space to make it printable.
  66.     mov [bx],ah        ; Put it in the packet.
  67.     mov ah,trans.rtime    ; Get the receive packet time out.
  68.     add ah,' '        ; Add a space.
  69.     mov 1[bx],ah        ; Put it in the packet.
  70.     mov ah,trans.rpad    ; Get the number of padding chars.
  71.     add ah,' '
  72.     mov 2[bx],ah        ; Put it in the packet.
  73.     mov ah,trans.rpadch    ; Get the padding char.
  74.     add ah,100O        ; Uncontrol it.
  75.     and ah,7FH
  76.     mov 3[bx],ah        ; Put it in the packet.
  77.     mov ah,trans.reol    ; Get the EOL char.
  78.     add ah,' '
  79.     mov 4[bx],ah        ; Put it in the packet.
  80.     mov ah,trans.rquote    ; Get the quote char.
  81.     mov 5[bx],ah        ; Put it in the packet.
  82.     mov ah,trans.ebquot    ; Get 8-bit quote char. [21b]
  83.     mov 6[bx],ah        ; Add it to the packet. [21b] 
  84.     mov ah,trans.chklen    ; Length of checksum.
  85.     add ah,48        ; Make into a real digit.
  86.     mov 7[bx],ah
  87.     mov ah,rptq        ; Repeat quote char.
  88.     cmp ah,0        ; Null means no.
  89.     jne rpar0
  90.     mov ah,' '        ; Send a blank instead.
  91. rpar0:    mov 8[bx],ah
  92.     mov ah,09H        ; Nine pieces of data.
  93.     ret
  94. RPAR    ENDP
  95.  
  96. ;    This routine reads in all the send_init packet information.
  97.  
  98. SPAR    PROC    NEAR
  99.     cmp ax,1
  100.     jge sparx
  101.     mov ah,dspsiz        ; Data not supplied by host, use default.
  102.     jmp sparx2
  103. sparx:    mov temp4,ax        ; Save the number of arguments.
  104.     mov ah,trans.spsiz
  105.     cmp ah,dspsiz        ; Is current value the default?
  106.     jne sparx2        ; No, assume changed by user.
  107.     mov ah,[bx]        ; Get the max packet size.
  108.     sub ah,' '        ; Subtract a space.
  109.     cmp ah,spmin        ; Can't be below the minimum.
  110.     jge sparx1
  111.     mov ah,spmin
  112.     jmp sparx2
  113. sparx1:    cmp ah,spmax        ; Or above the maximum.
  114.     jle sparx2
  115.     mov ah,spmax
  116. sparx2:    mov trans.spsiz,ah    ; Save it.
  117.     mov ax,temp4
  118.     cmp al,2        ; Fewer than two pieces?
  119.     jge spar0
  120.     mov ah,dstime        ; Data not supplied by host, use default.
  121.     jmp spar02
  122. spar0:     mov ah,trans.stime
  123.     cmp ah,dstime        ; Is current value the default?
  124.     jne spar02        ; No, assume changed by user.
  125.     mov ah,1[bx]        ; Get the timeout value.
  126.     sub ah,' '        ; Subtract a space.
  127.     cmp ah,0
  128.     ja spar01        ; Must be non-negative.
  129.     mov ah,0
  130. spar01:    cmp ah,trans.rtime    ; Same as other side's timeout.
  131.     jne spar02
  132.     add ah,5        ; If so, make it a little different.
  133. spar02:    mov trans.stime,ah    ; Save it.
  134.     mov ax,temp4
  135.     cmp al,3        ; Fewer than three pieces?
  136.     jge spar1
  137.     mov ah,dspad        ; Data not supplied by host, use default.
  138.     jmp spar11
  139. spar1:    mov ah,trans.spad
  140.     cmp ah,dspad        ; Is current value the default?
  141.     jne spar11        ; No, assume changed by user.
  142.     mov ah,2[bx]        ; Get the number of padding chars.
  143.     sub ah,' '
  144.     cmp ah,0
  145.     ja spar11        ; Must be non-negative.
  146.     mov ah,0
  147. spar11:    mov trans.spad,ah
  148.     mov ax,temp4
  149.     cmp al,4        ; Fewer than four pieces?
  150.     jge spar2
  151.     mov ah,dspadc        ; Data not supplied by host, use default.
  152.     jmp spar21
  153. spar2:    mov ah,trans.spadch
  154.     cmp ah,dspadc        ; Is current value the default?
  155.     jne spar21        ; No, assume changed by user.
  156.     mov ah,3[bx]        ; Get the padding char.
  157.     add ah,100O        ; Re-controlify it.
  158.     and ah,7FH
  159.     cmp ah,del        ; Delete?
  160.     je spar21        ; Yes, then it's OK.
  161.     cmp ah,0
  162.     jge spar20
  163.     mov ah,0        ; Below zero is no good.
  164.     jmp spar21        ; Use zero (null).
  165. spar20:    cmp ah,31        ; Is it a control char?
  166.     jle spar21        ; Yes, then OK.
  167.     mov ah,0        ; No, use null.
  168. spar21:    mov trans.spadch,ah
  169.     mov ax,temp4
  170.     cmp al,5        ; Fewer than five pieces?
  171.     jge spar3
  172.     mov ah,dseol        ; Data not supplied by host, use default.
  173.     jmp spar31
  174. spar3:  mov ah,trans.seol
  175.     cmp ah,dseol        ; Is current value the default?
  176.     jne spar31        ; No, assume changed by user.
  177.     mov ah,4[bx]        ; Get the EOL char.
  178.     sub ah,' '
  179.     cmp ah,0
  180.     jge spar30        ; Cannot be negative.
  181.     mov ah,cr        ; If it is, use default of carriage return.
  182.     jmp spar31
  183. spar30:    cmp ah,31        ; Is it a control char?
  184.     jle spar31        ; Yes, then use it.
  185.     mov ah,cr        ; Else, use the default.
  186. spar31:    mov trans.seol,ah
  187.     mov ax,temp4
  188.     cmp al,6        ; Fewer than six pieces?
  189.     jge spar4
  190.     mov ah,dsquot        ; Data not supplied by host, use default.
  191.     jmp spar41
  192. spar4:    mov ah,trans.squote
  193.     cmp ah,dsquot        ; Is current value the default?
  194.     jne spar41        ; No, assume changed by user.
  195.     mov ah,5[bx]        ; Get the quote char.
  196.     cmp ah,' '        ; Less than a space?
  197.     jge spar40
  198.     mov ah,dsquot        ; Yes, use default.
  199.     jmp spar41
  200. spar40:    cmp ah,'~'        ; Must also be less then a tilde.
  201.     jle spar41
  202.     mov ah,dsquot        ; Else, use default.
  203. spar41:    mov trans.squote,ah
  204.     cmp al,7        ; Fewer than seven pieces? [21b begin]
  205.     jge spar5
  206.     mov trans.ebquot,'Y'    ; Data not supplied by host, use default.
  207.     jmp spar51
  208. spar5:    mov ah,6[bx]        ; Get other sides 8-bit quote request.
  209.     call doquo        ; And set quote char.  [21b end]
  210. spar51:    cmp al,8        ; Fewer than eight pieces?
  211.     jge spar6
  212.     mov trans.chklen,1
  213.     jmp spar61
  214. spar6:    mov ah,inichk
  215.     mov trans.chklen,ah    ; Checksum length we really want to use.
  216.     mov ah,7[bx]        ; Get other sides checksum length.
  217.     call dochk        ; Determine what size to use.
  218. spar61:    cmp al,9        ; Fewer than nine pieces?
  219.     jge spar7
  220.     mov rptq,0
  221.     ret
  222. spar7:    mov ah,8[bx]        ; Get other sides repeat count prefix.
  223.     mov ch,drpt
  224.     mov rptq,0
  225.     call dorpt
  226.     ret
  227. SPAR    ENDP
  228.  
  229. ; Set 8-bit quote character based on my capabilities and the other
  230. ; Kermit's request.   [21b]
  231.  
  232. DOQUO    PROC    NEAR
  233.     cmp trans.ebquot,'N'    ; Can I do 8-bit quoting at all?
  234.     je dq3            ; No - so forget it.
  235.     cmp trans.ebquot,'Y'    ; Can I do it if requested?
  236.     jne dq0            ; No - it's a must that I do it.
  237.     mov trans.ebquot,ah    ; Do whatever he wants.
  238.     jmp dq1
  239. dq0:    cmp ah,'Y'        ; I need quoting - can he do it?
  240.     je dq1            ; Yes - then all is settled.
  241.     cmp ah,'N'        ; No - then don't quote.
  242.     je dq3
  243.     cmp ah,trans.ebquot    ; Both need quoting - chars must match.
  244.     jne dq3
  245. dq1:    mov ah,trans.ebquot
  246.     cmp ah,'Y'        ; If Y or N, don't validate prefix.
  247.     je dq2
  248.     cmp ah,'N'
  249.     je dq2
  250.     call prechk        ; Is it in range 33-62, 96-126?
  251.      mov ah,'Y'        ; Failed, don't do quoting.
  252.      nop
  253.     cmp ah,trans.rquote    ; Same prefix?
  254.     je dq3            ; Not allowed, so don't do quoting. 
  255.     cmp ah,trans.squote    ; Same prefix here?
  256.     je dq3            ; This is illegal too.
  257.     mov trans.ebquot,ah    ; Remember what we decided on.
  258. dq2:    ret
  259. dq3:    mov trans.ebquot,'N'    ; Quoting will not be done.
  260.     ret
  261. DOQUO    ENDP
  262.  
  263. ; Check if prefix in AH is in the proper range: 33-62, 96-126. 
  264. ; RSKP if so else RETURN.
  265. prechk:    cmp ah,33
  266.     jge prec0        ; It's above 33.
  267.     ret
  268. prec0:    cmp ah,62
  269.     jg prec1
  270.     jmp rskp        ; And below 62.  OK.
  271. prec1:    cmp ah,96
  272.     jge prec2        ; It's above 96.
  273.     ret
  274. prec2:    cmp ah,126
  275.     jg prec3
  276.     jmp rskp        ; And below 126.  OK.
  277. prec3:    ret
  278.  
  279. ; Set checksum length. 
  280. dochk:    cmp ah,'1'        ; Must be 1, 2, or 3.
  281.     jl doc1
  282.     cmp ah,'3'
  283.     jle doc2
  284. doc1:    mov ah,'1'
  285. doc2:    sub ah,48        ; Don't want it printable.
  286.     cmp ah,trans.chklen    ; Do we want the same thing?
  287.     je dochk0        ; Yes, then we're done.
  288.     mov trans.chklen,1    ; No, use single character checksum.
  289. dochk0:    ret            ; Just return for now.
  290.  
  291. ; Set repeat count quote character.  The one used must be different than
  292. ; the control and eight-bit quote characters.  Also, both sides must 
  293. ; use the same character.
  294. dorpt:    call prechk        ; Is it in the valid range?
  295.      mov ah,0        ; No, don't use their value. 
  296.      nop
  297.     cmp ah,trans.squote    ; Same as the control quote char?
  298.     je dorpt0        ; Yes, that's illegal, no repeats.
  299.     cmp ah,trans.rquote    ; How about this one?
  300.     je dorpt0        ; No good.
  301.     cmp ah,trans.ebquot    ; Same as eight bit quote char?
  302.     je dorpt0        ; Yes, that's illegal too, no repeats.
  303.     cmp ah,ch        ; Are we planning to use the same char?
  304.     jne dorpt0        ; No, that's no good either.
  305.     mov rptq,ch        ; Use repeat quote char now.
  306. dorpt0:    ret
  307.  
  308. ;    Send command
  309.  
  310. SEND    PROC    NEAR
  311.     mov comand.cmcr,0    ; Filename must be specified.
  312.     mov difnam,0        ; Assume we'll use original filename.
  313.     mov flags.wldflg,0    ; Re-initialize every time.
  314.     mov ah,cmifi        ; Parse an input file spec.
  315.     mov dx,offset fcb    ; Give the address for the FCB.
  316.     mov bx,offset filhlp    ; Text of help message.
  317.     call comnd
  318.      jmp r            ;  Give up on bad parse.
  319.     cmp flags.wldflg,0FFH    ; Any wildcards seen?
  320.     je send1        ; Yes, get a confirm.
  321.     mov bx,offset sendas    ; See if want to send file under dif name.
  322.     mov dx,offset filmsg    ; In case user needs help.
  323.     mov ah,cmtxt
  324.     call comnd
  325.      jmp r
  326.     cmp ah,0        ; Different name supplied?
  327.     je send11        ; No - keep as it.
  328.     mov difnam,1        ; Yes - send different filename.
  329.     mov difsiz,ah        ; Remember length of new name.
  330.     jmp send11
  331. send1:  mov ah,cmcfm
  332.     call comnd        ; Get a confirm.
  333.      jmp r            ;  Didn't get a confirm.
  334. send11: mov flags.droflg,0    ; Reset flags from fn parsing. [21a]
  335.     mov flags.nmoflg,0    ; Reset flags from fn parsing. [21a]
  336.     mov ah,sfirst        ; Get the first file.
  337.     mov dx,offset fcb
  338.     int dos
  339.     cmp al,0FFH        ; Any found?
  340.     jne send12
  341.     cmp pack.state,'R'    ; was this from a remote GET?
  342.     jne sen11a        ; no, print error and continue
  343.     mov bx,offset remmsg1    ; else get error message
  344.     call errpack        ; go complain
  345.     jmp abort        ; and abort this
  346. sen11a:    mov ah,prstr
  347.     mov dx,offset crlf
  348.     int dos
  349.     mov ah,prstr
  350.     mov dx,offset erms15
  351.     int dos
  352.     ret
  353. send12: cmp flags.wldflg,0    ; Any wildcards.      [7 start]
  354.     je send16        ; Nope, so no problem.
  355.     mov bx,offset fcb    ; Remember what FCB looked like.
  356.     mov di,offset cpfcb
  357.     mov cl,37        ; Size of FCB.
  358.     call fcbcpy
  359.     mov di,offset fcb+1    ; Copy filename    from DTA to FCB.
  360.     mov bx,offset buff+1
  361.     mov cl,11
  362.     call fcbcpy                    ; [7 end]
  363. send16:    call serini        ; Initialize serial port. [14]
  364.     mov pack.pktnum,0    ; Set the packet number to zero.
  365.     mov pack.numtry,0    ; Set the number of tries to zero.
  366.     mov pack.numpkt,0     ; Set the number of packets to zero.
  367.     mov pack.numrtr,0    ; Set the number of retries to zero.
  368.     mov pack.state,'S'    ; Set the state to receive initiate.
  369.     cmp flags.remflg,0    ; remote mode?
  370.     jne send2a        ; yes, continue below.
  371.     call init        ; Clear the line and initialize the buffers.
  372.     call rtpos        ; Position cursor.
  373.     mov ax,0
  374.     call nout        ; Write the number of retries.
  375.     call stpos        ; Print status of file transfer.
  376.     mov ah,prstr        ; Be informative.
  377.     mov dx,offset infms2
  378.     int dos
  379. send2:    cmp flags.remflg,0    ; remote mode?
  380.     jne send2a        ; yes, skip printing
  381.     call nppos        ; Number of packets sent.
  382.     mov ax,pack.numpkt
  383.     call nout        ; Write the packet number.
  384. send2a:    cmp pack.state,'D'    ; Are we in the data send state?
  385.     jne send3
  386.     call sdata
  387.     jmp send2
  388. send3:  cmp pack.state,'F'    ; Are we in the file send state?
  389.     jne send4
  390.     call sfile        ; Call send file.
  391.     jmp send2
  392. send4:  cmp pack.state,'Z'    ; Are we in the EOF state?
  393.     jne send5
  394.     call seof
  395.     jmp send2
  396. send5:  cmp pack.state,'S'    ; Are we in the send initiate state?
  397.     jne send6
  398.     call sinit
  399.     jmp send2
  400. send6:  cmp pack.state,'B'    ; Are we in the eot state?
  401.     jne send7
  402.     call seot
  403.     jmp send2
  404. send7:  cmp pack.state,'C'    ; Are we in the send complete state?
  405.     jne send8
  406.     call serrst        ; Reset serial port.  [14]
  407.     cmp flags.remflg,0    ; remote mode?
  408.     jne send7a        ; yes, no printing.
  409.     cmp flags.cxzflg,0    ; completed normally?
  410.     jne send7b        ; no, don't bother with this
  411.     call perpos
  412.     mov ah,prstr
  413.     mov dx,offset infms7
  414.     int dos
  415. send7b:    call stpos
  416.     mov ah,prstr
  417.     mov dx,offset infms3    ; Plus a little cuteness.
  418.     cmp flags.cxzflg,0    ; Completed or interrupted?
  419.     je snd71        ; Ended normally.
  420.     mov dx,offset infms6    ; Say was interrupted.
  421. snd71:  int dos            ; New label. 
  422.     cmp flags.belflg,0    ; Bell desired? [17a]
  423.     je sendnb        ; [17a]
  424.     mov dx,offset ender    ; Ring them bells.   [4]
  425.     int dos
  426. sendnb:    call clrmod
  427.     call rprpos
  428. send7a:    jmp rskp
  429. send8:     call serrst        ; Reset serial port.  [14]
  430.     cmp flags.remflg,0    ; remote mode?
  431.     jne send9a        ; no, no printing.
  432.     call stpos
  433.     mov ah,prstr
  434.     mov dx,offset infms4    ; Plus a little cuteness.
  435.     int dos
  436.     cmp flags.belflg,0    ; Bell desired?  [17a]
  437.     je send9        ; No.  [17a]
  438.     mov dx,offset ender    ; Ring them bells.   [4]
  439.     int dos            ;  [4]
  440. send9:    call clrmod
  441.     call rprpos
  442. send9a:    jmp rskp
  443. SEND    ENDP
  444.  
  445.  
  446. ;    Send routines
  447.  
  448. ;    Send initiate
  449.  
  450.  
  451. SINIT    PROC    NEAR
  452.     cmp pack.numtry,imxtry    ; Have we reached the maximum number of tries?
  453.     jl sinit2
  454.     call erpos
  455.     mov dx,offset erms14
  456.     mov ah,prstr
  457.     int dos            ; Print an error message.
  458.     mov bx,offset erms20
  459.     call errpack        ; Send error packet just in case.
  460.     jmp abort        ; Change the state to abort.
  461. sinit2: inc pack.numtry        ; Save the updated number of tries.
  462.     mov bx,offset data    ; Get a pointer to our data block.
  463.     call rpar        ; Set up the parameter information.
  464.     xchg ah,al
  465.     mov ah,0
  466.     mov pack.argbk1,ax    ; Save the number of arguments.
  467.     mov ax,pack.numpkt    ; Get the packet number.
  468.     mov pack.argblk,ax
  469.     mov ah,trans.chklen
  470.     mov curchk,ah        ; Store checksum length we want to use.
  471.     mov trans.chklen,1    ; Send init checksum is always 1 char.
  472.     mov ah,'S'        ; Send initiate packet.
  473.     call spack        ; Send the packet.
  474.      jmp abort
  475.     call rpack        ; Get a packet.
  476.      jmp sini23        ; Trashed packet don't change state, retry.
  477.     push ax
  478.     mov ah,curchk
  479.     mov trans.chklen,ah    ; Checksum length we want to use.
  480.     pop ax
  481.     cmp ah,'Y'        ; ACK?
  482.     jne sinit3        ; If not try next.
  483.     mov ax,pack.pktnum    ; Get the packet number.
  484.     cmp ax,pack.argblk    ; Is it the right packet number?
  485.     je sini22
  486.     ret            ; If not try again.
  487. sini22: inc ax            ; Increment the packet number.
  488.     and ax,3FH        ; Turn off the two high order bits.
  489.     mov pack.pktnum,ax    ; Save modulo 64 of the number.
  490.     inc pack.numpkt        ; Increment the number of packets.
  491.     mov ax,pack.argbk1    ; Get the number of pieces of data.
  492.     mov bx,offset data    ; Pointer to the data.
  493.     call spar        ; Read in the data.
  494.     call packlen        ; Get max send packet size. [21b]
  495.     mov ah,pack.numtry    ; Get the number of tries.
  496.     mov pack.oldtry,ah    ; Save it.
  497.     mov pack.numtry,0    ; Reset the number of tries.
  498.     mov pack.state,'F'    ; Set the state to file send.
  499.     call getfil        ; Open the file.
  500.      jmp abort        ;  Something is wrong, die.
  501.     mov filopn,1        ; Disk file is open.
  502.     ret
  503. sini23:    mov ah,curchk        ; Restore desired checksum length.
  504.     mov trans.chklen,ah
  505.     call updrtr        ; Update retry counter.
  506.     ret            ; And retry.
  507. sinit3: cmp ah,'N'        ; NAK?
  508.     jne sinit4        ; If not see if its an error.
  509.     call rtpos        ; Position cursor.
  510.     inc pack.numrtr        ; Increment the number of retries
  511.     mov ax,pack.numrtr
  512.     call nout        ; Write the number of retries.
  513.     ret
  514. sinit4: cmp ah,'E'        ; Is it an error packet.
  515.     jne sinit5
  516.     call error
  517. sinit5: jmp abort
  518. SINIT    ENDP
  519.  
  520.  
  521.  
  522. ;    Send file header
  523.  
  524. SFILE    PROC    NEAR
  525.     cmp pack.numtry,maxtry    ; Have we reached the maximum number of tries?
  526.     jl sfile1
  527.     call erpos
  528.     mov dx,offset erms14
  529.     mov ah,prstr
  530.     int dos            ; Print an error message.
  531.     mov bx,offset erms21
  532.     call errpack        ; Send error packet just in case.
  533.     jmp abort        ; Change the state to abort.
  534. sfile1: inc pack.numtry        ; Increment it.
  535.     mov flags.cxzflg,0    ; Clear ^X,^Z flag. 
  536.     mov datptr,offset data  ; Get a pointer to our data block.
  537.     mov bx,offset fcb+1        ; Pointer to file name in FCB.
  538.     mov fcbpt,bx        ; Save position in FCB.
  539.     mov cl,0        ; Counter for chars in file name.
  540.     mov ch,0        ; Counter for number of chars in FCB.
  541. sfil11:    cmp ch,8H        ; Ninth char?
  542.     jne sfil12
  543.     mov ah,'.'
  544.     mov bx,datptr
  545.     mov [bx],ah        ; Put dot in data packet.    
  546.     inc bx
  547.     mov datptr,bx        ; Save new position in data packet.
  548.     inc cl
  549. sfil12:    inc ch
  550.     cmp ch,0CH        ; Twelve?
  551.     jns sfil13
  552.     mov bx,fcbpt
  553.     mov ah,[bx]        ; Get char of filename.
  554.     inc bx
  555.     mov fcbpt,bx        ; Save position in FCB.
  556.     cmp ah,'!'        ; Is it a good char?
  557.     jl sfil11        ; If not, get the next.
  558.     mov bx,datptr
  559.     mov [bx],ah        ; Put char in data buffer.
  560.     inc cl            ; Increment counter.
  561.     inc bx
  562.     mov datptr,bx        ; Save new position. 
  563.     jmp sfil11        ; Get another char.
  564. sfil13: mov ch,0
  565.     cmp flags.remflg,0    ; remote mode?
  566.     jne sfil13a        ; yes, no printing.
  567.     push cx            ; Don't forget the size.
  568.     mov bx,datptr
  569.     mov ah,'$'
  570.     mov [bx],ah        ; Put dollar sign for printing.
  571.     call clrfln
  572.     mov ah,prstr
  573.     mov dx,offset data    ; Print file name.
  574.     int dos
  575.     pop cx
  576. sfil13a:cmp difnam,0        ; Sending file under different name.
  577.     je sfl13x        ; No, so don't give new name.
  578.     call newfn
  579. sfl13x:    call doenc        ; Do encoding.
  580.     mov ax,pack.pktnum    ; Get the packet number.
  581.     mov pack.argblk,ax
  582.     mov ah,'F'        ; File header packet.
  583.     call spack        ; Send the packet.
  584.      jmp abort
  585.     call rpack        ; Get a packet.
  586.      jmp tryagn        ; Trashed packet don't change state, retry.
  587.     call dodec        ; Do all decoding.
  588.     cmp ah,'Y'        ; ACK?
  589.     jne sfile2        ; If not try next.
  590.     mov ax,pack.pktnum    ; Get the packet number.
  591.     cmp ax,pack.argblk
  592.     je sfil14
  593.     ret            ; If not hold out for the right one.
  594. sfil14: inc ax            ; Increment the packet number.
  595.     and ax,3FH        ; Turn off the two high order bits.
  596.     mov pack.pktnum,ax    ; Save modulo 64 of the number.
  597.     inc pack.numpkt        ; Increment the number of packets.
  598.     mov ah,pack.numtry    ; Get the number of tries.
  599.     mov pack.oldtry,ah    ; Save it.
  600.     mov pack.numtry,0    ; Reset the number of tries.
  601.  
  602. sfil15: mov ah,0        ; Get a zero.
  603.     mov bx,offset fcb
  604.     add bx,20H
  605.     mov [bx],ah        ; Set the record number to zero.
  606. ;    mov flags.eoflag,ah    ; Indicate not EOF.  (Done in GETFIL).
  607.     mov ah,0FFH
  608.     mov flags.filflg,ah    ; Indicate file buffer empty.
  609.     call gtchr
  610.      jmp sfil16        ; Error go see if its EOF.
  611.      nop
  612.     jmp sfil17        ; Got the chars, proceed.
  613. sfil16: cmp ah,0FFH        ; Is it EOF?
  614.     je sfl161
  615.     jmp abort        ; If not give up.
  616. sfl161: mov ah,'Z'        ; Set the state to EOF.
  617.     mov pack.state,ah
  618.     ret
  619. sfil17: mov siz,ax
  620.  
  621.     mov pack.state,'D'    ; Set the state to data send.
  622.     ret
  623. sfile2: cmp ah,'N'        ; NAK?
  624.     jne sfile3        ; Try if error packet.
  625.     call rtpos        ; Position cursor.
  626.     inc pack.numrtr        ; Increment the number of retries
  627.     mov ax,pack.numrtr
  628.     call nout        ; Write the number of retries.
  629.     mov ax,pack.pktnum    ; Get the present packet number.
  630.     inc ax            ; Increment.
  631.     and ax,03FH        ; Account for wraparound.  [18]
  632.     cmp ax,pack.argblk    ; Is the packet's number one more than now?
  633.     jz sfil14        ; Just as good as a ACK; go to the ACK code.
  634.     ret            ; If not go try again.
  635. sfile3: cmp ah,'E'        ; Is it an error packet.
  636.     jne sfile4
  637.     call error
  638. sfile4: jmp abort
  639. SFILE    ENDP
  640.  
  641.  
  642. ;    Send data
  643.  
  644. SDATA    PROC    NEAR
  645.     cmp flags.cxzflg,0    ; Have we seen ^X or ^Z?
  646.     je sdata2        ; Nope, just continue.
  647.     cmp flags.cxzflg,'C'    ; Stop it all? [25]
  648.     jne sdata1        ; It was a ^X or ^Z.
  649.     mov pack.state,'A'    ; It was a ^C -- abort [25]
  650.     ret
  651. sdata1:    mov pack.state,'Z'    ; Else, abort sending the file.
  652.     ret
  653. sdata2: cmp pack.numtry,maxtry    ; Have we reached the maximum number of tries?
  654.     jl sdata3
  655.     call erpos
  656.     mov dx,offset erms14
  657.     mov ah,prstr
  658.     int dos            ; Print an error message.
  659.     mov bx,offset erms22
  660.     call errpack        ; Send error packet just in case.
  661.     jmp abort        ; Change the state to abort.
  662. sdata3: inc pack.numtry        ; Increment it.
  663.     mov datptr,offset data  ; Get a pointer to our data block.
  664.     mov chrptr,offset filbuf ; Pointer to chars to be sent.
  665.     mov cx,siz        ; number to transfer
  666.     mov si,chrptr        ; source of characters
  667.     mov di,datptr        ; destination
  668. ;    cmp flags.eofcz,0    ; stopping on ctl-z's?
  669. ;    jz sdata6        ; no, do blind copy
  670. ;sdata4:    lodsb            ; get a byte
  671. ;    cmp al,'Z'-40H        ; is it a ctl-z?
  672. ;    je sdata5        ; yes, break loop
  673. ;    stosb            ; else copy it
  674. ;    loop sdata4        ; and keep going
  675. ;sdata5:    mov ax,siz        ; size to send
  676. ;    sub ax,cx        ; minus actually sent...
  677. ;    jmp short sdata7
  678. ;sdata6:    
  679.     rep movsb        ; just copy data
  680.     mov ax,siz        ; this is how many were moved
  681. sdata7:    mov pack.argbk1,ax
  682.     mov ax,pack.pktnum    ; Get the packet number.
  683.     mov pack.argblk,ax
  684.     mov ah,'D'        ; Data packet.
  685.     call spack        ; Send the packet.
  686.      jmp tryagn        ; if can't send it, retry before giving up
  687.     call rpack        ; Get a packet.
  688.      jmp tryagn        ; Trashed packet don't change state, retry.
  689.     call dodec        ; Do all decoding.
  690.     cmp ah,'Y'        ; ACK?
  691.     jne sdat14        ; If not try next.
  692.     mov ax,pack.pktnum    ; Get the packet number.
  693.     cmp ax,pack.argblk    ; Is it the right packet number?
  694.     jz sdata8
  695.     ret            ; If not hold out for the right one.
  696. sdata8: inc ax            ; Increment the packet number.
  697.     and ax,3FH        ; Turn off the two high order bits.
  698.     mov pack.pktnum,ax    ; Save modulo 64 of the number.
  699.     inc pack.numpkt        ; Increment the number of packets.
  700.     mov ah,pack.numtry    ; Get the number of tries.
  701.     mov pack.oldtry,ah    ; Save it.
  702.     mov pack.numtry,0    ; Reset the number of tries.
  703.     cmp pack.argbk1,1    ; Does the ACK contain data?
  704.     jne sdat11        ; Nope, so continue.
  705.     mov bx,offset data    ; If yes, check the data field.
  706.     mov ah,[bx]        ; Pick it up.
  707.     cmp ah,'X'        ; Other side requests ^X?
  708.     jne sdata9        ; Nope.
  709.     jmp sdat10        ; And leave.
  710. sdata9: cmp ah,'Z'        ; Other side requests ^Z?
  711.     jne sdat11        ; Nope.
  712. sdat10:    mov flags.cxzflg,ah    ; Yes remember it.
  713.     mov pack.state,'Z'    ; Abort sending file(s).
  714.     ret
  715. sdat11: call gtchr
  716.      jmp sdat12        ; Error go see if its EOF.
  717.     mov siz,ax        ; Save the size of the data gotten.
  718.     ret
  719.  
  720. sdat12: cmp ah,0FFH        ; Is it EOF?
  721.     je sdat13
  722.     jmp abort        ; If not give up.
  723.  
  724. sdat13: mov pack.state,'Z'    ; Set the state to EOF.
  725.     ret
  726. sdat14: cmp ah,'N'        ; NAK?
  727.     jne sdat15        ; See if is an error packet.
  728.     call rtpos        ; Position cursor.
  729.     inc pack.numrtr        ; Increment the number of retries
  730.     mov ax,pack.numrtr
  731.     call nout        ; Write the number of retries.
  732.     mov ax,pack.pktnum    ; Get the present packet number.
  733.     inc ax            ; Increment.
  734.     and ax,03FH        ; Account for wraparound.  [18]
  735.     cmp ax,pack.argblk    ; Is the packet's number one more than now?
  736.     jz sdata8        ; Just as good as ACK; goto ACK code.
  737.     ret            ; If not go try again.
  738. sdat15: cmp ah,'E'        ; Is it an error packet.
  739.     jne sdat16
  740.     call error
  741. sdat16: jmp abort
  742. SDATA    ENDP
  743.  
  744.  
  745. ;    Send EOF
  746.  
  747. SEOF    PROC    NEAR
  748.     cmp pack.numtry,maxtry    ; Have we reached the maximum number of tries?
  749.     jl seof1
  750.     call erpos        ; Position cursor.
  751.     mov dx,offset erms14
  752.     mov ah,prstr
  753.     int dos            ; Print an error message.
  754.     mov bx,offset erms23
  755.     call errpack        ; Send error packet just in case.
  756.     jmp abort        ; Change the state to abort.
  757. seof1:  inc pack.numtry        ; Increment it.
  758.     mov ax,pack.pktnum    ; Get the packet number.
  759.     mov pack.argblk,ax
  760.     mov pack.argbk1,0    ; No data.
  761.     cmp flags.cxzflg,0    ; Seen a ^X or ^Z?
  762.     je seof11        ; Nope, send normal EOF packet.
  763.     mov bx,offset data    ; Get data area of packet.
  764.     mov ah,'D'        ; Use "D" for discard.
  765.     mov [bx],ah        ; And add it to the packet.
  766.     mov pack.argbk1,1    ; Set data size to 1.
  767. seof11:    mov cx,pack.argbk1    ; Put size in CX.
  768.     call doenc        ; Encode the packet.
  769.     mov ah,'Z'        ; EOF packet.
  770.     call spack        ; Send the packet.
  771.      jmp abort
  772.     call rpack        ; Get a packet.
  773.      jmp tryagn        ;  Trashed packet don't change state, retry.
  774.     call dodec        ; Do decoding.
  775.     cmp ah,'Y'        ; ACK?
  776.     jne seof2        ; If not try next.
  777.     mov ax,pack.pktnum    ; Get the packet number.
  778.     cmp ax,pack.argblk    ; Is it the right packet number?
  779.     jz seof12
  780.     ret            ; If not hold out for the right one.
  781. seof12: inc ax            ; Increment the packet number.
  782.     and ax,3FH        ; Turn off the two high order bits.
  783.     mov pack.pktnum,ax    ; Save modulo 64 of the number.
  784.     inc pack.numpkt        ; Increment the number of packets.
  785.     mov ah,pack.numtry    ; Get the number of tries.
  786.     mov pack.oldtry,ah    ; Save it.
  787.     mov pack.numtry,0    ; Reset the number of tries.
  788.     mov ah,closf        ; Close the file.
  789.     mov dx,offset fcb
  790.     int dos
  791.     call gtnfil        ; Get the next file.
  792.      jmp seof13        ;  No more.
  793.     mov pack.state,'F'    ; Set the state to file send.
  794.     cmp flags.cxzflg,'X'    ; Control-X seen?
  795.     jne seof14
  796.     call cxmsg        ; Clear out the interrupt msg.
  797. seof14:    mov flags.cxzflg,0    ; Reset the flag.
  798.     ret
  799. seof13: mov pack.state,'B'    ; Set the state to EOT.
  800.     mov filopn,0        ; No files open.
  801.     ret
  802. seof2:  cmp ah,'N'        ; NAK?
  803.     jne seof3        ; Try and see if its an error packet.
  804.     call rtpos        ; Position cursor.
  805.     inc pack.numrtr        ; Increment the number of retries
  806.     mov ax,pack.numrtr
  807.     call nout        ; Write the number of retries.
  808.     mov ax,pack.pktnum    ; Get the present packet number.
  809.     inc ax            ; Increment.
  810.     and ax,03FH        ; Account for wraparound.  [18]
  811.     cmp ax,pack.argblk    ; Is the packet's number one more than now?
  812.     jz seof12        ; Just as good as a ACK; go to the ACK code.
  813.     ret            ; If not go try again.
  814. seof3:  cmp ah,'E'        ; Is it an error packet?
  815.     jne seof4
  816.     call error
  817. seof4:  jmp abort
  818. SEOF    ENDP
  819.  
  820.  
  821. ;    Send EOT
  822.  
  823. SEOT    PROC    NEAR
  824.     cmp pack.numtry,maxtry    ; Have we reached the maximum number of tries?
  825.     jl seot1
  826.     call erpos           ; Position cursor.
  827.     mov dx,offset erms14
  828.     mov ah,prstr
  829.     int dos            ; Print an error message.
  830.     mov bx,offset erms24
  831.     call errpack        ; Send error packet just in case.
  832.     jmp abort        ; Change the state to abort.
  833. seot1:  inc pack.numtry        ; Increment it.
  834.     mov ax,pack.pktnum    ; Get the packet number.
  835.     mov pack.argblk,ax
  836.     mov pack.argbk1,0    ; No data.
  837.     mov cx,pack.argbk1
  838.     call doenc        ; Encode packet.
  839.     mov ah,'B'        ; EOF packet.
  840.     call spack        ; Send the packet.
  841.      jmp abort
  842.     call rpack        ; Get a packet.
  843.      jmp tryagn        ; Trashed packet don't change state, retry.
  844.     call dodec        ; Decode packet.
  845.     cmp ah,'Y'        ; ACK?
  846.     jne seot2        ; If not try next.
  847.     mov ax,pack.pktnum    ; Get the packet number.
  848.     cmp ax,pack.argblk    ; Is it the right packet number?
  849.     jz seot12
  850.     ret            ; If not hold out for the right one.
  851. seot12: inc ax            ; Increment the packet number.
  852.     and ax,3FH        ; Turn off the two high order bits.
  853.     mov pack.pktnum,ax    ; Save modulo 64 of the number.
  854.     inc pack.numpkt        ; Increment the number of packets.
  855.     mov ah,pack.numtry    ; Get the number of tries.
  856.     mov pack.oldtry,ah    ; Save it.
  857.     mov pack.numtry,0    ; Reset the number of tries.
  858.     mov pack.state,'C'    ; Set the state to file send.
  859.     ret
  860. seot2:  cmp ah,'N'        ; NAK?
  861.     jne seot3        ; Is it error.
  862.     call rtpos        ; Position cursor.
  863.     inc pack.numrtr        ; Increment the number of retries
  864.     mov ax,pack.numrtr
  865.     call nout        ; Write the number of retries.
  866.     mov ax,pack.pktnum    ; Get the present packet number.
  867.     inc ax            ; Increment.
  868.     and ax,03FH        ; Account for wraparound.  [18]
  869.     cmp ax,pack.argblk    ; Is the packet's number one more than now?
  870.     jz seot12        ; Just as good as a ACK; go to the ACK code.
  871.     ret            ; If not go try again.
  872. seot3:  cmp ah,'E'        ; Is it an error packet.
  873.     jne seot4
  874.     call error
  875. seot4:  jmp abort
  876. SEOT    ENDP
  877.  
  878. tryagn:    call updrtr
  879.     ret
  880.  
  881. newfn:    mov ah,prstr
  882.     mov dx,offset asmsg
  883.     int dos
  884.     mov ah,dconio
  885.     mov si,offset sendas    ; Buffer where the name is.
  886.     mov di,offset data
  887.     mov ch,0
  888.     mov cl,difsiz        ; Length of name.
  889. newf0:    lodsb            ; Get a char.
  890.     cmp al,61H
  891.     jb newf1        ; Leave alone if less than 'a'?
  892.     cmp al,7AH
  893.     ja newf1        ; Leave alone if over 'z'.
  894.     sub al,20H        ; Uppercase the letters.
  895. newf1:    stosb
  896.     mov dl,al
  897.     cmp flags.remflg,0    ; should we print?
  898.     jne newf2        ; no, we're in remote mode.
  899.     int dos            ; Print them.
  900. newf2:    loop newf0
  901.     mov ch,0
  902.     mov cl,difsiz        ; Reset the length field.
  903.     ret
  904.  
  905. ; Do encoding.  Expectx CX to be the data size.
  906. doenc:    jcxz doen0
  907.     mov chrcnt,cx        ; Number of chars in filename.
  908.     mov bx,offset data    ; Source of data.
  909.     mov bufpnt,bx
  910.     mov bx,offset nulref    ; Null routine for refilling buffer.
  911.     mov ah,rptq
  912.     mov origr,ah        ; Save repeat prefix here.
  913.     mov rptct,1        ; Number of times char is repeated.
  914.     mov rptval,0        ; Value of repeated char.
  915.     call encode        ; Make a packet with size in AX.
  916.      nop
  917.      nop
  918.      nop
  919.     mov pack.argbk1,ax    ; Save number of char in filename.
  920.     mov cx,ax
  921.     call movpak        ; Move to data part of packet.
  922. doen0:    ret
  923.  
  924. ; CX is set before this is called.
  925. movpak:    push es
  926.     mov ax,ds
  927.     mov es,ax
  928.     mov si,offset filbuf    ; Move from here
  929.     mov di,offset data    ; to here
  930.     repne movsb
  931.     pop es
  932.     ret
  933.  
  934. ; Do decoding.
  935. dodec:    cmp pack.argbk1,0
  936.     je dodc0
  937.     push ax            ; Save packet size.
  938.     mov cx,pack.argbk1    ; Size of data.
  939.     mov bx,offset data    ; Address of data.
  940.     mov ax,offset nulr    ; Routine to dump buffer (null routine).
  941.     mov bufpnt,offset decbuf  ; Where to put output.
  942.     mov chrcnt,80H        ; Buffer size.
  943.     call decode
  944.      nop     
  945.      nop     
  946.      nop     
  947.     call decmov        ; Move decoded data back to "data" buffer.
  948.      pop ax
  949. dodc0:    ret
  950.  
  951. ; Move decoded data from decode buffer back to "data". 
  952. decmov:    push si
  953.     push di
  954.     push es
  955.     mov ax,ds
  956.     mov es,ax
  957.     mov cx,bufpnt        ; Last char we added.
  958.     sub cx,offset decbuf    ; Get actual number of characters.
  959.     mov pack.argbk1,cx    ; Remember size of real data.
  960.     lea si,decbuf        ; Data is here.
  961.     lea di,data        ; Move to here.
  962.     repne movsb        ; Copy the data.
  963.     mov al,0        ; Null to end the string.
  964.     stosb
  965.     pop es
  966.     pop di
  967.     pop si
  968.     ret
  969.  
  970. ;    Abort
  971.  
  972. ABORT    PROC    NEAR
  973.     cmp filopn,0        ; Any disk files open?
  974.     je abort0        ; No so don't do a close.
  975.     mov ah,closf        ; Close the file and ignore errors.
  976.     mov dx,offset fcb
  977.     int dos
  978. abort0:    mov pack.state,'A'    ; Otherwise abort.
  979.     ret
  980. ABORT    ENDP
  981.  
  982. ; This is where we go if we get an error packet.  A call to ERROR 
  983. ; positions the cursor and prints the message.  A call to ERROR1
  984. ; just prints a CRLF and then the message.  [8]
  985.  
  986. ERROR    PROC    NEAR
  987.     mov pack.state,'A'    ; Set the state to abort.
  988.     call erpos        ; Position the cursor.
  989.     jmp error2
  990. error1:    mov ah,prstr
  991.     mov dx,offset crlf
  992.     int dos
  993. error2: mov bx,pack.argbk1    ; Get the length of the data.
  994.     add bx,offset data    ; Get to the end of the string.
  995.     mov ah,'$'        ; Put a dollar sign at the end.
  996.     mov [bx],ah
  997.     mov ah,prstr        ; Print the error message.
  998.     mov dx,offset data
  999.     int dos
  1000.     ret
  1001. ERROR    ENDP
  1002.  
  1003. ; Set the maximum data packet size. [21b]
  1004.  
  1005. PACKLEN    PROC    NEAR
  1006.     mov ah,trans.spsiz    ; Maximum send packet size. 
  1007.     sub ah,4        ; Size minus control info. 
  1008.     sub ah,trans.chklen    ; And minus checksum chars.
  1009.     sub ah,2        ; Leave room at end: 2 for possible #X.
  1010.     cmp trans.ebquot,'N'    ; Doing 8-bit quoting?
  1011.     je pack0        ; Nope so we've got our size.
  1012.     cmp trans.ebquot,'Y'
  1013.     je pack0        ; Not doing it in this case either.
  1014.     sub ah,1        ; Another 1 for 8th-bit quoting. 
  1015. pack0:    cmp rptq,0        ; Doing repeat character quoting?
  1016.     je pack1        ; Nope, so that's all for now.
  1017.     sub ah,2        ; Another 2 for repeat prefix.
  1018. pack1:    mov trans.maxdat,ah    ; Save max length for data field.
  1019.     ret
  1020. PACKLEN    ENDP
  1021.  
  1022.  ; Print the number in AX on the screen in decimal rather that hex. [19a]
  1023.  
  1024. NOUT     PROC    NEAR
  1025.     cmp flags.xflg,1    ; Writing to screen? [21c]
  1026.     je nout1        ; Yes, just leave. [21c]
  1027.     push ax
  1028.     push dx
  1029.     mov temp,10        ; Divide quotient by 10.
  1030. ;    cwd            ; Convert word to doubleword.
  1031.     mov dx,0        ; High order word should be zero.
  1032.     div temp        ; AX <-- Quo, DX <-- Rem.
  1033.     cmp ax,0        ; Are we done?    
  1034.     jz nout0        ; Yes.
  1035.     call nout        ; If not, then recurse.
  1036. nout0:    add dl,'0'        ; Make it printable.
  1037.     mov temp,ax
  1038.     mov ah,conout
  1039.     int dos    
  1040.     mov ax,temp
  1041.     pop dx
  1042.     pop ax
  1043. nout1:    ret            ; We're done. [21c]
  1044. NOUT    ENDP
  1045.  
  1046. ; Jumping to this location is like retskp.  It assumes the instruction
  1047. ;   after the call is a jmp addr.
  1048.  
  1049. RSKP    PROC    NEAR
  1050.     pop bp
  1051.     add bp,3
  1052.     push bp
  1053.     ret
  1054. RSKP    ENDP
  1055.  
  1056. ; Jumping here is the same as a ret.
  1057.  
  1058. R    PROC    NEAR
  1059.     ret
  1060. R    ENDP
  1061.  
  1062. code    ends 
  1063.     end
  1064.